import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import $ from 'jquery';
import { withProps } from '../PropsComponent';

const onContextMenu = (event) => {
	event.preventDefault();
};

class Li extends React.Component {
	onClick = (...args) => {
		const { disabled, onClick, onItemTrigger } = this.props;
		if (!disabled) {
			if (onClick) onClick(...args);
			onItemTrigger();
		}
	};

	render() {
		const { ...props } = this.props;
		delete props.disabled;
		delete props.list;
		delete props.onItemTrigger;
		return <li role="button" {...props} onClick={this.onClick} />;
	}
}

Li.propTypes = {
	disabled: PropTypes.bool,
	onClick: PropTypes.func,
	onItemTrigger: PropTypes.func,
};

const PLi = withProps(Li);

class MenuList extends React.Component {
	constructor() {
		super();
		this.state = {
			x: 0,
			y: 0,
			show: false,
			activeList: undefined,
			itemRect: undefined,
		};
	}

	componentWillMount() {
		const { x, y, parentRect } = this.props;
		this.relocate({ x, y, parentRect });
	}

	componentWillReceiveProps(nextProps) {
		this.relocate(nextProps);
	}

	onClick = (event) => {
		event.stopPropagation();
	};

	onItemTrigger = () => {
		this.props.onMenuTrigger();
	};

	onItemMouseEnter = (event, itemProps) => {
		const { disabled, list } = itemProps;
		if (disabled || !list) return;
		this.setState({
			activeList: list,
			itemRect: event.currentTarget.getBoundingClientRect(),
		});
	};

	onItemMouseLeave = (event, itemProps) => {
		const { disabled, list } = itemProps;
		if (disabled || !list) return;
		this.setState({ activeList: undefined, itemRect: undefined });
	};

	setMenuRef = (ele) => {
		this.$menu = ele;
	};

	relocate = ({ x, y, parentRect }) => {
		this.setState({ x, y, show: false });
		const pRect = parentRect || { left: x, top: y, right: x, bottom: y, width: 0, height: 0 };

		Promise.resolve().then(() => {
			const rect = this.$menu.getBoundingClientRect();
			const winHeight = window.innerHeight;
			const winWidth = $('body').innerWidth();
			let newX = pRect.right;
			let newY = pRect.top - 1;

			if (winHeight < newY + rect.height) {
				newY = winHeight - rect.height;
			}

			if (winWidth < newX + rect.width) {
				newX = pRect.left - rect.width;
			}

			this.setState({ x: newX, y: newY, show: true });
		});
	};

	render() {
		const { list = [], onMenuTrigger } = this.props;
		const { x, y, show, activeList, itemRect } = this.state;
		const hasIcon = list.some(({ icon }) => icon);

		return (
			<ul
				role="button" className={classNames('bdp-menu-list', show && 'active')} style={{ left: x, top: y }}
				onContextMenu={onContextMenu} onClick={this.onClick} ref={this.setMenuRef}
			>
				{list.map(({ title, disabled, split, icon, onClick, list: subList }, index) => {
					return (
						<PLi
							key={index} role="button" className={classNames({ disabled, split, hasIcon })}
							disabled={disabled} list={subList} onClick={onClick}
							onItemTrigger={this.onItemTrigger}
							onMouseEnter={this.onItemMouseEnter} onMouseLeave={this.onItemMouseLeave}
						>
							{hasIcon && <span className={classNames('bdp-menu-icon', 'fa', `fa-${icon}`)} />}
							<div className="btn-menu-title">
								{title}
								{subList && <span className="fa fa-caret-right bdp-menu-title-caret" />}
							</div>
							{subList && activeList === subList ?
							<MenuList
								list={subList} parentRect={itemRect} onMenuTrigger={onMenuTrigger}
							/> : null}
						</PLi>
					);
				})}
				{list.length === 0 && <li className="disabled">(Empty List)</li>}
			</ul>
		);
	}
}

MenuList.propTypes = {
	list: PropTypes.array,
	x: PropTypes.number,
	y: PropTypes.number,
	parentRect: PropTypes.object,
	onMenuTrigger: PropTypes.func,
};

export default MenuList;
